home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 January / macpower199701.bin / AMUG / Programming_10 / WASTE 1.3a1.sit / WASTE 1.3a1 Distribution / Extras / WASTE Tabs 1.3.2 / WETabHooks.c next >
Encoding:
C/C++ Source or Header  |  1996-08-23  |  6.2 KB  |  282 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WETabHooks.c
  3.  *
  4.  *    WASTE TABS PACKAGE
  5.  *    Hooks for adding tab support to WASTE
  6.  *
  7.  *    Written by:
  8.  *        Mark Alldritt (original code)
  9.  *        Dan Crevier (line breaks)
  10.  *        John Daub (maintenance)
  11.  *        Jonathan Kew (variable-width tabs)
  12.  *        Marco Piovanelli (?)
  13.  *        Bert Seltzer (horizontal scrolling)
  14.  *
  15.  */
  16.  
  17. #include "WETabs.h"
  18. #include "WETabHooks.h"
  19.  
  20. #define FIXROUND(f)            ((SInt16) (((f) + 0x00008000) >> 16))
  21. #define BSL(A, B)            (((SInt32) (A)) << (B))
  22.  
  23. static const Point kOneToOneScaling = { 1, 1 } ;
  24.  
  25. pascal void _WETabDrawText
  26.     (
  27.         Ptr pText,
  28.         SInt32 textLength,
  29.         Fixed slop,
  30.         JustStyleCode styleRunPosition,
  31.         WEReference we
  32.     )
  33. {
  34. #pragma unused ( slop, styleRunPosition )
  35.  
  36.     LongRect destRect;
  37.     SInt32 beginChar = 0;
  38.     SInt32 ii;
  39.     SInt16 tabWidth;
  40.     SInt16 destLeft;
  41.     Point penPos;
  42.     SInt16 tabSize = WEGetTabSize(we);
  43.  
  44.     WEGetDestRect(&destRect, we);
  45.     destLeft = (SInt16) destRect.left;
  46.  
  47.     for ( ii = 0; ii < textLength; ii++ )
  48.     {
  49.         if (pText[ii] == '¥t')
  50.         {
  51.             DrawText(pText, beginChar, ii - beginChar);
  52.  
  53.             /* advance the pen to the next tab stop */
  54.             GetPen(&penPos);
  55.             tabWidth = tabSize - (penPos.h - destLeft) % tabSize;
  56.             MoveTo(penPos.h + tabWidth, penPos.v);
  57.             beginChar = ii + 1;
  58.         }
  59.     }    /* for */
  60.  
  61.     DrawText(pText, beginChar, textLength - beginChar);
  62. }
  63.  
  64. pascal SInt32 _WETabPixelToChar
  65.     (
  66.         Ptr pText,
  67.         SInt32 textLength,
  68.         Fixed slop,
  69.         Fixed *width,
  70.         WEEdge *edge,
  71.         JustStyleCode styleRunPosition,
  72.         Fixed hPos,
  73.         WEReference we
  74.     )
  75. {
  76.     SInt32 beginChar = 0;
  77.     SInt32 offset = 0;
  78.     SInt32 ii;
  79.     Fixed lastWidth;
  80.     Fixed tabWidth;
  81.     SInt16 tabSize = WEGetTabSize(we);
  82.  
  83.     /* loop through every character in the segment looking for tabs */
  84.     for ( ii = 0; ii < textLength; ii++ )
  85.     {
  86.         /* exit now if width has gone negative */
  87.         /* (i.e., if we have found which glyph was hit) */
  88.         if (*width <= 0)
  89.         {
  90.             break;
  91.         }
  92.  
  93.         /* tab found? */
  94.         if (pText[ii] == '¥t')
  95.         {
  96.             /* calculate the width of the sub-segment preceding the tab */
  97.             lastWidth = *width;
  98.             offset += PixelToChar(pText + beginChar, ii - beginChar, slop,
  99.                     lastWidth, (Boolean *) edge, width, styleRunPosition,
  100.                     kOneToOneScaling, kOneToOneScaling);
  101.             beginChar = ii + 1;
  102.  
  103.             /* hit point past sub-segment? */
  104.             if (*width >= 0)
  105.             {
  106.                 /* increment hPos by width of sub-segment preceding the tab */
  107.                 hPos += (lastWidth - *width);
  108.  
  109.                 /* calculate the width of the tab "glyph" (as a Fixed value) */
  110.                 tabWidth = BSL(tabSize - FIXROUND(hPos) % tabSize, 16);
  111.  
  112.                 /* increment hPos by width of tab character */
  113.                 hPos += tabWidth;
  114.  
  115.                 /* hit point within tab glyph? */
  116.                 if (*width < tabWidth)
  117.                 {
  118.                     /* yes: determine which half of tab glyph was hit */
  119.                     if (*width > (tabWidth >> 1))
  120.                     {
  121.                         *edge = kTrailingEdge;    /* second (trailing) edge of tab */
  122.                         offset++;
  123.                     }
  124.                     else
  125.                     {
  126.                         *edge = kLeadingEdge;    /* first (leading) edge of tab */
  127.                     }
  128.  
  129.                     /* returning -1 (as Fixed) in width means we're finished */
  130.                     *width = 0xFFFF0000;
  131.                 }
  132.                 else
  133.                 {
  134.                     /* hit point is past tab: keep looping */
  135.                     offset++;
  136.                     *width -= tabWidth;
  137.                 }
  138.             } /* if (*width >= 0) */
  139.         } /* if tab found */
  140.     } /* for */
  141.  
  142.     /* no more tabs in this segment: process the last sub-segment */
  143.     if (*width >= 0)
  144.     {
  145.         lastWidth = *width;
  146.         offset += PixelToChar(pText + beginChar, textLength - beginChar, slop,
  147.                     lastWidth, (Boolean *) edge, width, styleRunPosition,
  148.                     kOneToOneScaling, kOneToOneScaling);
  149.     }
  150.  
  151.     /* round width to nearest integer value */
  152.     /* this is supposed to fix an incompatibility with the WorldScript Power Adapter */
  153.     *width = (*width + 0x00008000) & 0xFFFF0000;
  154.  
  155.     return offset;
  156. }
  157.  
  158. pascal SInt16 _WETabCharToPixel
  159.     (
  160.         Ptr pText,
  161.         SInt32 textLength,
  162.         Fixed slop,
  163.         SInt32 offset,
  164.         SInt16 direction,
  165.         JustStyleCode styleRunPosition,
  166.         SInt16 hPos,
  167.         WEReference we
  168.     )
  169. {
  170.     LongRect destRect;
  171.     SInt32 beginChar = 0;
  172.     SInt32 ii;
  173.     SInt16 width;
  174.     SInt16 destLeft;
  175.     SInt16 totalWidth = 0;
  176.     SInt16 tabSize = WEGetTabSize(we);
  177.  
  178.     WEGetDestRect(&destRect, we);
  179.     destLeft = (SInt16) destRect.left;
  180.  
  181.     /* measure text up to offset, if offset is within this segment,
  182.         otherwise to textLength */
  183.     if (offset > textLength)
  184.     {
  185.         offset = textLength;
  186.     }
  187.  
  188.     for ( ii = 0; ii < offset; ii++ )
  189.     {
  190.         if (pText[ii] == '¥t')
  191.         {
  192.             /* calculate the pixel width of the subsegment preceding the tab */
  193.             width = TextWidth(pText, beginChar, ii - beginChar);
  194.             totalWidth += width;
  195.             hPos += width;
  196.  
  197.             /* calculate tab width */
  198.             width = tabSize - (hPos - destLeft) % tabSize;
  199.             totalWidth += width;
  200.             hPos += width;
  201.  
  202.             /* go to next subsegment */
  203.             beginChar = ii + 1;
  204.         }
  205.     } /* for */
  206.  
  207.     /* calculate width of remaining characters */
  208.     width = CharToPixel(pText + beginChar, textLength - beginChar, slop,
  209.                         offset - beginChar, direction, styleRunPosition,
  210.                         kOneToOneScaling, kOneToOneScaling);
  211.     totalWidth += width;
  212.  
  213.     return totalWidth;
  214. }
  215.  
  216. pascal StyledLineBreakCode _WETabLineBreak
  217.     (
  218.         Ptr pText,
  219.         SInt32 textLength,
  220.         SInt32 textStart,
  221.         SInt32 textEnd,
  222.         Fixed *textWidth,
  223.         SInt32 *textOffset,
  224.         WEReference we
  225.     )
  226. {
  227.     LongRect destRect;
  228.     SInt32 beginChar = textStart;
  229.     SInt32 ii;
  230.     Fixed tabWidth;
  231.     SInt16 destWidth;
  232.     StyledLineBreakCode breakCode = smBreakOverflow;
  233.     SInt16 tabSize = WEGetTabSize(we);
  234.  
  235.     WEGetDestRect(&destRect, we);
  236.     destWidth = (SInt16) (destRect.right - destRect.left);
  237.  
  238.     for ( ii = textStart; ii < textEnd; ii++ )
  239.     {
  240.         if (pText[ii] == 0x0D)
  241.         {
  242.             /* found a <return>, so stop looking ahead for tabs */
  243.             ii++;
  244.             break;
  245.         }
  246.         if (pText[ii] == '¥t')
  247.         {
  248.             /* do previous "segment" */
  249.             breakCode = StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
  250.             if ((breakCode != smBreakOverflow) || (ii >= textLength))
  251.             {
  252.                 break;
  253.             }
  254.             beginChar = ii + 1;
  255.  
  256.             /* calculate tab width (as a Fixed value) */
  257.             tabWidth = BSL(tabSize - (destWidth - FIXROUND(*textWidth)) % tabSize, 16);
  258.  
  259.             /* if tabWidth > pixelWidth we break in tab */
  260.             /* don't move tab to next line */
  261.             if (tabWidth > *textWidth)
  262.             {
  263.                 breakCode = smBreakWord;
  264.                 *textOffset = ii + 1;
  265.                 break;
  266.             }
  267.             else
  268.             {
  269.                 *textWidth -= tabWidth;
  270.             }
  271.         }
  272.     } /* for */
  273.  
  274.     /* do last sub-segment */
  275.     if ((ii - beginChar >= 0) && (breakCode == smBreakOverflow))
  276.     {
  277.         breakCode = StyledLineBreak(pText, textLength, beginChar, ii, 0, textWidth, textOffset);
  278.     }
  279.  
  280.     return breakCode;
  281. }
  282.